import { Pinyin } from "../../pinyin/Pinyin";

export const newLine = "\r\n";
export interface ICls {
    toString(tabNum?: number);
    name: string;
}

export class IJson implements ICls {
    private _name: string;
    private _varList: Array<IVar>;
    private _des: string;
    constructor(name: string) {
        this._name = name;
        this._varList = [];
    }
    public get name(): string {
        return this._name;
    }
    public setDes(des: string) {
        this._des = des;
    }
    addVar(name: string, type: string, des: string) {
        for (let i = 0; i < this._varList.length; i++) {
            let value: IVar = this._varList[i];
            if (value.name == name) {
                return;
            }
        }
        this._varList.push(new IVar(name, type, des));
    }

    toString(tabNum: number = 0) {
        var result = `${gettab(tabNum)}interface ${this._name} {${newLine}`;
        for (var i = 0; i < this._varList.length; i++) {
            result += this._varList[i].toString(tabNum + 1) + newLine;
        }

        result += gettab(tabNum) + "}";
        return result;
    }

}

export class IInterface implements ICls {
    private _name: string;
    private _funcList: Array<IFunction>;
    private _varList: Array<IVar>;
    constructor(name: string) {
        this._name = name;
        this._funcList = [];
        this._varList = [];
    }

    public get name(): string {
        return this._name;
    }

    //获取当前类，或者接口的主键 string
    getPrimaryKey() {
        let kv = this._varList.filter(v => v.primaryKey)[0];
        if (kv != null) return kv.name;
        return "";
    }

    addFunction(name: string, des: string, type: string = "void") {
        this._funcList.push(new IFunction(name, des, type));
    }

    addVar(name: string, type: string, des: string, isPrimaryKey = false) {
        for (let i = 0; i < this._varList.length; i++) {
            let value: IVar = this._varList[i];
            if (value.name == name) {
                return;
            }
        }
        this._varList.push(new IVar(name, type, des, isPrimaryKey));
    }

    toString(tabNum: number = 0) {
        var result = `${gettab(tabNum)}interface ${this._name} {${newLine}`;
        for (var i = 0; i < this._varList.length; i++) {
            result += this._varList[i].toString(tabNum + 1) + newLine;
        }

        for (var i = 0; i < this._funcList.length; i++) {
            result += this._funcList[i].toString(tabNum + 1) + newLine;
        }
        result += gettab(tabNum) + "}";
        return result;
    }
}

function gettab(num: number = 1): string {
    var result = "";
    var i = 0;
    while (i < num) {
        result += "\t";
        i++;
    }
    return result;
}

export class IFunction {
    private _name: string;
    private _des: string;
    private _type: string;
    constructor(name: string, des: string, type: string) {
        this._name = name;
        this._des = des != null ? des.replace(/\//g, "\\\/") : "";
        this._type = type;
    }

    toString(tabNum: number = 0) {
        return `${gettab(tabNum)}\/**${this._des}*\/${newLine}${gettab(tabNum)}${this._name}():${this._type};`;
    }
}

export class IVar {
    private _name: string;
    private _type: string;
    private _des: string;
    primaryKey: boolean;
    constructor(name: string, type: string, des: string, isPrimaryKey = false) {
        this._name = name;
        this._type = type;
        this._des = des != null ? des.replace(/\//g, "\\\/") : "";
        this.primaryKey = isPrimaryKey;
    }

    public get name(): string {
        return this._name;
    }
    public get isPrimaryKey() { return this.primaryKey; }

    toString(tabNum: number = 0) {
        return `${gettab(tabNum)}\/**${this._des}*\/${newLine}${gettab(tabNum)}${this._name}?:${this._type};`;
    }
}

export class IEnum implements ICls {
    private _name: string;
    private _varList: Array<IEnumVar>;
    private _hash: any;
    private _des: string = "";
    constructor(name: string) {
        this._name = name;
        this._varList = [];
        this._hash = {};
    }

    public setDes(des: string) {
        this._des = des;
    }

    addVar(name: string, value: number, des: string) {
        var iVar = new IEnumVar(name, value, des);
        this._varList.push(iVar);
        this._hash[name] = iVar;
    }

    getValue(name: string) {
        if (!name) return 0;
        let pinYinKey = Pinyin.Inst.getFullChars(name);
        if (this._hash[pinYinKey] == null) {
            throw new Error(this._name + "枚举类型对应错误:" + name);
        }
        return this._hash[pinYinKey].value;
    }

    toString(tabNum: number = 0) {
        var result = `${gettab(tabNum)}enum ${this._name}{${newLine}`;
        if (!!this._des) {
            result = `${gettab(tabNum)}\/**${this._des}*\/${newLine}` + result;
        }
        for (var i = 0; i < this._varList.length; i++) {
            result += this._varList[i].toString(tabNum + 1) + newLine;
        }
        result += gettab(tabNum) + "}";
        return result;
    }

    get name(): string {
        return this._name;
    }
}

export class IEnumVar {
    private _name: string;
    private _value: number;
    private _des: string;
    constructor(name: string, value: number, des: string) {
        this._name = name;
        this._value = value;
        this._des = des;
    }

    public toString(tabNum: number = 0) {
        return `${gettab(tabNum)}${this._name}=${this._value},      \/\/${this._des}`;
    }

    public get value(): number {
        return this._value;
    }
}

export class ITags implements ICls {
    private _name: string;
    private _varList: Array<ITagsVar>;
    private _hash: any;
    private _des: string = "";
    constructor(name: string) {
        this._name = name;
        this._varList = [];
        this._hash = {};
    }

    public setDes(des: string) {
        this._des = des;
    }

    addVar(name: string, value: number, des: string) {
        var iVar = new ITagsVar(name, Math.pow(2, value), des);
        this._varList.push(iVar);
        this._hash[name] = iVar;
    }

    getValue(name: string) {
        if (!name) return 0;
        let pinYinKey = Pinyin.Inst.getFullChars(name);
        if (this._hash[pinYinKey] == null) {
            throw new Error(this._name + "tag类型对应错误:" + name);
        }
        return this._hash[pinYinKey].value;
    }

    toString(tabNum: number = 0) {
        var result = `${gettab(tabNum)}const ${this._name}={${newLine}`;
        if (!!this._des) {
            result = `${gettab(tabNum)}\/**${this._des}*\/${newLine}` + result;
        }
        for (var i = 0; i < this._varList.length; i++) {
            result += this._varList[i].toString(tabNum + 1) + newLine;
        }
        result += gettab(tabNum) + "}";
        return result;
    }

    get name(): string {
        return this._name;
    }
}

export class ITagsVar {
    private _name: string;
    private _value: number;
    private _des: string;
    constructor(name: string, value: number, des: string) {
        this._name = name;
        this._value = value;
        this._des = des;
    }

    public toString(tabNum: number = 0) {
        return `${gettab(tabNum)}${this._name}:${this._value},      \/\/${this._des}`;
    }

    public get value(): number {
        return this._value;
    }
}


export class IConst implements ICls {
    private _name: string;
    private _varList: Array<IConstVar>;
    private _hash: any;
    private _des: string = "";
    constructor(name: string) {
        this._name = name;
        this._varList = [];
        this._hash = {};
    }

    public setDes(des: string) {
        this._des = des;
    }

    addVar(name: string, value: string, des: string) {
        var iVar = new IConstVar(name, value, des);
        this._varList.push(iVar);
        this._hash[name] = iVar;
    }

    getValue(name: string) {
        return this._hash[name] ? this._hash[name].value : 0;
    }

    toString(tabNum: number = 0) {
        var result = `${gettab(tabNum)}const ${this._name}={${newLine}`;
        if (!!this._des) {
            result = `${gettab(tabNum)}\/**${this._des}*\/${newLine}` + result;
        }
        for (var i = 0; i < this._varList.length; i++) {
            result += this._varList[i].toString(tabNum + 1) + newLine;
        }
        result += gettab(tabNum) + "}";
        return result;
    }

    get name(): string {
        return this._name;
    }
}

export class IConstVar {
    private _name: string;
    private _value: string;
    private _des: string;
    constructor(name: string, value: string, des: string) {
        this._name = name;
        this._value = value;
        this._des = des;
    }

    public toString(tabNum: number = 0) {
        return `${gettab(tabNum)}${this._name}:\"${this._value}\",      \/\/${this._des}`;
    }

    public get value(): string {
        return this._value;
    }
}